package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"unsafe"
)
//storange Session
type Session struct {
	AccessToken   string `json:"access_token"`
	RefreshToken  string `json:"refresh_token"`
	SessionKey    string `json:"session_key"`
	SessionSecret string `json:"session_secret"`
	Scope         string `json:"scope"`
	ExpiresIn     int    `json:"expires_in"`
}
//Package simple class
type faceIdentify struct {
	token string
	clientID string
	clientSecret string
}

//Constructor method
func Newface(clientID string,clientSecret string) faceIdentify{
	return faceIdentify{
		"",
		clientID,
		clientSecret,
	}
}
//GET access_token
func (face *faceIdentify)getTokenAndStorage()  error{
	apiURL := fmt.Sprintf("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s", face.clientID, face.clientSecret)
	resp, err := http.Get(apiURL)
	if err != nil {
		return  err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return  err
	}
	var session Session
	err = json.Unmarshal(body, &session)
	if err != nil {
		return  err
	}
	face.token=session.AccessToken
	return  nil
}


//Add a Group(Library management)
func (face faceIdentify)addGroup(groupid string) {
	apiURL := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/add?access_token=%s", face.token)
	//创建map存放body数据
	data:=make(map[string]string,1)
	data["group_id"]=groupid
	mjson,err:=json.Marshal(data)
	if err != nil {
		fmt.Println(err)
	}
	//---------------test------------------
	param:=(*string)(unsafe.Pointer(&mjson))
	fmt.Println(*param)
	resp, err := http.Post(apiURL, "application/json", strings.NewReader(*param))
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}

	All:=(*(*string)(unsafe.Pointer(&body)))
	all:=strings.Split(All,",")
	temp:=all[0]
	res:=strings.Split(temp,":")
	if res[1]=="0"{
		fmt.Println("Success add Group")
	}else{
		fmt.Println("Fail add Group")
	}
}
//delete group from baidu Library
func (face faceIdentify)deleteGroup(groupid string) error{
	if face.token==""{
		fmt.Println(errors.New("token is empty!"))
	}
	apiURL := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/delete?access_token=%s", face.token)
	//创建map存放body数据
	data:=make(map[string]string,1)
	//分配数据
	data["group_id"]=groupid
	mjson,err:=json.Marshal(data)
	if err != nil {
		panic(err)
		return err
	}
	param:=(*string)(unsafe.Pointer(&mjson))
	resp, err := http.Post(apiURL, "application/json", strings.NewReader(*param))
	if err != nil {
		panic(err)
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
		return err
	}
	All:=(*(*string)(unsafe.Pointer(&body)))
	all:=strings.Split(All,",")
	temp:=all[0]
	facestring:=strings.Split(temp,":")
	if facestring[1]=="0"{
		fmt.Println("删除组成功")
	}else{
		fmt.Println("删除组失败")
	}
	return nil
}
//Search the face in baidu database,return the access_token (string[0]) and name in Library (string[1])
func (face faceIdentify)search(groupid string,imagedata string) []string {
	apiURL := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=%s", face.token)
	//创建map存放body数据
	data:=make(map[string]string,3)
	//storage the data
	data["group_id_list"]=groupid
	data["image"]=imagedata
	data["image_type"]="BASE64"
	mjson,err:=json.Marshal(data)
	if err != nil {
		fmt.Println(err)
	}
	param:=(*string)(unsafe.Pointer(&mjson))
	resp, err := http.Post(apiURL, "application/json", strings.NewReader(*param))
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}

	All:=(*(*string)(unsafe.Pointer(&body)))
	var res []string
	all:=strings.Split(All,",")
	temp:=all[5]
	facestring:=strings.Split(temp,":")
	fin:=facestring[2]
	res=append(res,fin[1:len(fin)-1])
	usertemp:=all[7]
	userdata:=strings.Split(usertemp,":")
	P:=userdata[1]
	res=append(res,P[1:len(P)-1])
	return res
}
//register a face，return the face_token
func (face faceIdentify)register(groupid string,userid string,imagedata string) (string,error) {
	apiURL := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=%s", face.token)
	//创建map存放body数据
	data:=make(map[string]string,4)
	//分配数据
	data["group_id"]=groupid
	data["image"]=imagedata
	data["user_id"]=userid
	data["image_type"]="BASE64"
	mjson,err:=json.Marshal(data)
	if err != nil {
		panic(err)
		return "",err
	}
	param:=(*string)(unsafe.Pointer(&mjson))
	resp, err := http.Post(apiURL, "application/json", strings.NewReader(*param))
	if err != nil {
		panic(err)
		return "",err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
		return "",err
	}

	All:=(*(*string)(unsafe.Pointer(&body)))
	all:=strings.Split(All,",")
	fmt.Println(all)
	temp:=all[5]
	facestring:=strings.Split(temp,":")
	fin:=facestring[2]
	res:=fin[1:len(fin)-1]
	return res,nil
}
//Attention!the Upload facedata will cover All the original data!
func (face faceIdentify)update(imagedata string,groupid string,userid string) (string,error) {
	apiURL := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/update?access_token=%s", face.token)
	//创建map存放body数据
	data:=make(map[string]string,4)
	//分配数据
	data["group_id"]=groupid
	data["image"]=imagedata
	data["user_id"]=userid
	data["image_type"]="BASE64"
	mjson,err:=json.Marshal(data)
	if err != nil {
		panic(err)
		return "",err
	}
	param:=(*string)(unsafe.Pointer(&mjson))
	resp, err := http.Post(apiURL, "application/json", strings.NewReader(*param))
	if err != nil {
		panic(err)
		return "",err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
		return "",err
	}

	All:= *(*string)(unsafe.Pointer(&body))
	all:=strings.Split(All,",")
	temp:=all[5]
	facestring:=strings.Split(temp,":")
	fin:=facestring[2]
	res:=fin[1:len(fin)-1]
	return res,nil
}
//delete from Library,return the corresponding face_token
func (face faceIdentify)deletefaceFromtoken(userid string,groupid string,facetoken string)  error{
	apiURL := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/faceset/face/delete?access_token=%s", face.token)
	//创建map存放body数据
	data:=make(map[string]string,3)
	data["group_id"]=groupid
	data["user_id"]=userid
	data["face_token"]=facetoken
	mjson,err:=json.Marshal(data)
	if err != nil {
		return err
	}
	param:=(*string)(unsafe.Pointer(&mjson))
	//---------------test------------------
	fmt.Println(*param)
	//--------------test------------------
	resp, err := http.Post(apiURL, "application/json", strings.NewReader(*param))
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	All:=(*(*string)(unsafe.Pointer(&body)))
	all:=strings.Split(All,",")
	temp:=all[0]
	facestring:=strings.Split(temp,":")
	if facestring[1]=="0"{
		fmt.Println("删除成功")
	}else{
		fmt.Println("删除图片失败")
	}
	return nil
}

//image transfer to Base64 string data
func (face faceIdentify)imgToBase64(url string) (string,error){
	faceImgdata,err:= ioutil.ReadFile(url)
	imagedata :=base64.StdEncoding.EncodeToString(faceImgdata)
	if err != nil {
		return "",err
	}
	return imagedata,nil
}


func main(){
	//badidu account
	clientID:="5enILvHvyGrI9XvqilHFFYeg"
	clientSecret:="zHP8vupGAud8oe1nrLU9bfMNkD8W7vxG"
	//fetch the photo information

	//create simple
	simple:=Newface(clientID,clientSecret)
	// image to Base64
	TrumpImg,err:=simple.imgToBase64("main/FaceIdentify/Trump.jpg")
	Trump2Img,err:=simple.imgToBase64("main/FaceIdentify/Trump2.jpg")
	Trump3Img,err:=simple.imgToBase64("main/FaceIdentify/Trump3.jpg")            //未注册
	QiangdongImg,err:=simple.imgToBase64("main/FaceIdentify/Qiangdong.jpg")
	Qiangdong2Img,err:=simple.imgToBase64("main/FaceIdentify/Qiangdong2.jpg")		//未注册
	MayunImg,err:=simple.imgToBase64("main/FaceIdentify/Mayun.jpg")
	if err != nil {
		fmt.Println("ImageToText()", err)
		return
	}
	// GET access_token method
	err = simple.getTokenAndStorage()
	err=simple.deleteGroup("yql")
	err=simple.deleteGroup("V")
	simple.addGroup("test")

	Trumptoken,err:=simple.register("test","Trump",TrumpImg)
	Trump2token,err:=simple.register("test","Trump",Trump2Img)
	Qiangdongtoken,err:=simple.register("test","Qiangdong",QiangdongImg)
	Mayuntoken,err:=simple.register("test","Mayun",MayunImg)
	fmt.Println("Trump:",Trumptoken)
	fmt.Println("Trump2",Trump2token)
	fmt.Println("强东：",Qiangdongtoken)

	searchtoken:=simple.search("test",Trump3Img)		//通过未注册图像查找
	search2token:=simple.search("test",Qiangdong2Img)	//同上
	fmt.Println("Trump3:",searchtoken)
	fmt.Println("强东2",search2token)

	TrumpAftertoken,err:=simple.update(Trump3Img,"test","Trump")
	fmt.Println("Trump更新后",TrumpAftertoken)
	simple.deletefaceFromtoken("Mayun","test",Mayuntoken)
	simple.deleteGroup("test")
}
